<template>
  <div class="camera_array">
    <div class="canvas" ref="canvas"></div>
  </div>
</template>

<script lang="ts">
import { Vue, Options } from 'vue-property-decorator';
import * as THREE from 'three';
const scene =  new THREE.Scene();
const ambient = new THREE.AmbientLight(0x222244);
scene.add(ambient);
const light = new THREE.DirectionalLight();
light.position.set(0.5, 0.5, 1);
light.castShadow = true;
light.shadow.camera.zoom = 4;
scene.add(light);

const renderer = new THREE.WebGLRenderer({
  alpha: true,
  antialias: true,
});
renderer.debug.checkShaderErrors = false;
renderer.setClearColor(new THREE.Color(), 0);
renderer.setPixelRatio(750 / window.innerWidth);
renderer.shadowMap.enabled = true;
const amount = 6;
let camera!: THREE.ArrayCamera;
let mesh!: THREE.Mesh;
let WIDTH = 0;
let HEIGHT = 0;
@Options({ components: {} })
export default class CameraArray extends Vue {
  public rect: DOMRect|null = null;

  public onWindowResize() {
    WIDTH  = (window.innerWidth / amount) * window.devicePixelRatio;
    HEIGHT  = (window.innerHeight / amount) * window.devicePixelRatio;
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    for (let y = 0;y < amount;y++) {
      for (let x = 0;x < amount;x++) {
        const subcamera = camera.cameras[amount * y + x];
        subcamera.setViewOffset(
          window.innerWidth, window.innerHeight,
          WIDTH * x, HEIGHT * y,
          WIDTH, HEIGHT,
        );
        subcamera.aspect = window.innerWidth / window.innerHeight;
        subcamera.updateProjectionMatrix();
      }
    }
    renderer.setSize(window.innerWidth, window.innerHeight);
  }
  public mounted() {
    this.rect = (this.$el as HTMLElement).getBoundingClientRect();
    renderer.setSize(this.rect.width, this.rect.height, false);
    (this.$refs.canvas as HTMLDivElement).append(renderer.domElement);
    WIDTH  = (window.innerWidth / amount) * window.devicePixelRatio;
    HEIGHT  = (window.innerHeight / amount) * window.devicePixelRatio;
    const cameras = [];

    for (let y = 0;y < amount;y++) {
      for (let x = 0;x < amount;x++) {
        const subcamera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
        subcamera.setViewOffset(
          window.innerWidth, window.innerHeight,
          WIDTH * x, HEIGHT * y,
          WIDTH, HEIGHT,
        );
        subcamera.position.x = (x / amount) - 0.5;
        subcamera.position.y = 0.5 - (y / amount);
        subcamera.position.z = 5;
        subcamera.position.multiplyScalar(2);
        subcamera.lookAt(0, 0, 0);
        subcamera.updateMatrixWorld();
        cameras.push(subcamera);
      }
    }
    camera = new THREE.ArrayCamera(cameras);
    camera.position.z = 3;

    const geometryBackground = new THREE.PlaneGeometry(100, 100);
    const materialBackground = new THREE.MeshPhongMaterial({ color: 0x0000666 });
    const background = new THREE.Mesh(geometryBackground, materialBackground);
    background.receiveShadow  = true;
    background.position.set(0, 0, -100);
    scene.add(background);
    const geometryCylinder = new THREE.CylinderGeometry(0.5, 0.5, 1, 32);
    const materialCylinder = new THREE.MeshPhongMaterial({ color: 0xff0000 });
    mesh = new THREE.Mesh(geometryCylinder, materialCylinder);
    mesh.castShadow = true;
    mesh.receiveShadow = true;
    scene.add(mesh);

    renderer.setAnimationLoop(() => {
      mesh.rotation.x += 0.005;
      mesh.rotation.z += 0.01;
      renderer.render(scene, camera);
    });

    window.addEventListener('resize', this.onWindowResize);
  }
}
</script>

<style lang="postcss" scoped>
  .camera_array{
    touch-action: none;
    position: absolute;
    left: 0;top: 0;
    width: 100%;height: 100%;
    background: #98bbd1;
     .canvas{
      position: absolute;
      left: 0;top: 0;
      width: 100%;height: 100%;
       :deep(canvas){
        width: 100%;height: 100%;
      }
    }
  }
</style>
